import Layers from "@/lang/layers/index";

const modules = import.meta.glob("../view/**/*.vue");

let router = undefined;

/**
 * 菜单元素
 */
export interface MenuItemType {

    /**
     * 菜单标题
     *
     * 用户能看到的菜单标题
     */
    title: string;

    /**
     * 菜单名称
     *
     * - 菜单栏对应的英文名，一般是有实际含义、小写的 url-safe 英文单词；
     * - 后台算法逻辑上使用的菜单名称；
     * - 相对于父级菜单，需要保证唯一；
     * - 用于 url 拼接，拼接完，实际就是 path 字段；
     */
    name: string;

    /**
     * 路由地址
     *
     * 由 name 字段拼接而成的路径，在浏览器输入这个地址可访问对应的界面
     */
    path: string;

    /**
     * 路由名称
     *
     * 由 path 转换而来的唯一 ID，功能与 path 基本一致，也可用于访问界面。
     *
     * 具体可搜索： vue3 路由
     */
    route_name: string;

    /**
     * 图标
     *
     * 支持 font-icon4，做为 i 标签的 html-class 使用
     */
    icon: string;

    /**
     * 静态资源路径
     *
     * html/vue 源代码在工程中的相对地址
     */
    src: string;

    /**
     * 子级菜单
     */
    children: MenuItemType[];

    /**
     * 是否命中查询条件
     *
     * 用于制作模糊搜索功能
     */
    hit: boolean;

    /**
     * 当前正在使用的界面
     *
     * 使用 el-menu 实现的界面不需要用到这个属性，
     * 如果需要调用相关功能，可以使用当前字段
     */
    active: boolean;
}

class MenuItem implements MenuItemType{

    public title;
    /**
     * 构造函数
     *
     * @param {string} title - 菜单标题
     * @param {string} name - 菜单名称
     * @param {string} icon - 菜单图标
     * @param {string} src - 静态资源路径
     * @param {MenuItem[]} children - 子菜单项数组
     */
    constructor(title, name = '', icon = '', src = '', children = []) {

        this.title = title;
        /**
         * 菜单名称
         *
         * 逻辑上使用的菜单名称；
         * 相对于父级菜单，需要保证唯一；
         * 用于 url 拼接，因此必须是有实际含义的英文单词；
         *
         * @type {string}
         */
        this.name = name;
        /**
         * 图标
         *
         * 支持 font-icon4，允许作为 html-class 使用
         *
         * @type {string}
         */
        this.icon = icon;
        /**
         * 静态资源路径
         *
         * html/vue 源代码在工程中的相对地址
         *
         * @type {string}
         */
        this.src = src;

        /**
         * 子级菜单
         *
         * @type {MenuItem[]}
         */
        this.children = children;

        /**
         * 路由地址
         *
         * 由 name 字段拼接而成的路径，在浏览器输入这个地址可访问对应的界面
         *
         * @type {string}
         */
        this.path = '';

        /**
         * 路由名称
         *
         * 由 path 转换而来的唯一 ID，功能与 path 基本一致，也可用于访问界面。
         *
         * 具体可搜索： vue3 路由
         *
         * @type {string}
         */
        this.route_name = '';

        /**
         * 是否命中查询条件
         *
         * 用于制作模糊搜索功能
         */
        this.hit = false;

        /**
         * 当前正在使用的界面
         *
         * 使用 el-menu 实现的界面不需要用到这个属性，
         * 如果需要调用相关功能，可以使用当前字段
         */
        this.active = false;
    }
}

/**
 * 代码样例
 *
 * 一整套代码样例
 *
 * @type {[MenuItem]}
 */
const $example = [
    new MenuItem('Base', 'base', 'fa fa-fw fa-laptop', '', [
        new MenuItem('ICON', 'icons', 'fa fa-fw fa-circle-o', 'example/ui/icons.vue')
        , new MenuItem('COLOR', 'color', 'fa fa-fw fa-circle-o', 'example/ui/color.vue')
        , new MenuItem('GENERAL', 'general', 'fa fa-fw fa-circle-o', 'example/ui/general.vue')
        , new MenuItem('ARTICLE', 'article', 'fa fa-fw fa-circle-o', 'example/ui/article.vue')
        , new MenuItem('LAYOUT', 'layout', 'fa fa-fw fa-circle-o', 'example/ui/layout.vue')
    ])

    , new MenuItem('UI', 'ui', 'fa fa-fw fa-laptop', '', [
        new MenuItem('ANIMATION', 'anim', 'fa fa-fw fa-circle-o', 'example/ui/anim.vue')
        , new MenuItem('BUTTONS', 'buttons', 'fa fa-fw fa-circle-o', 'example/ui/buttons.vue')
        , new MenuItem('CHAT', 'chat', 'fa fa-fw fa-circle-o', 'example/ui/chat.vue')
        , new MenuItem('TIMELINE', 'timeline', 'fa fa-fw fa-circle-o', 'example/ui/timeline.vue')
        , new MenuItem('POPOVER', 'popover', 'fa fa-fw fa-circle-o', 'example/ui/popover.vue')
    ])

    , new MenuItem('异常', 'error', 'fa fa-fw fa-gamepad', '', [
        new MenuItem('403', 'E403', '', 'error/E403.vue')
        , new MenuItem('404', 'E404', '', 'error/E404.vue')
        , new MenuItem('500', 'E500', '', 'error/E500.vue')
    ])

    , new MenuItem('图表', 'charts', 'fa fa-fw fa-gamepad', '', [
        new MenuItem('Test', 'test', '', 'example/charts/test.vue')
        , new MenuItem('Title', 'title', '', 'example/charts/title.vue')
        , new MenuItem('Bar', 'bar', '', 'example/charts/bar.vue')
    ])

    , new MenuItem('邮箱', 'mail', 'fa fa-fw fa-envelope', '', [
        new MenuItem('发件箱', 'compose', '', 'example/mail/compose.vue')
        , new MenuItem('邮件', 'inbox', '', 'example/mail/inbox.vue')
        , new MenuItem('收件箱', 'read', '', 'example/mail/read.vue')
    ])

    , new MenuItem('Box', 'box', 'fa fa-fw fa-clipboard', '', [
        new MenuItem('PRODUCT', 'product', 'fa fa-fw fa-circle-o', 'example/box/product.vue')
        , new MenuItem('INFO-BOX', 'infobox', 'fa fa-fw fa-circle-o', 'example/box/info-box.vue')
        , new MenuItem('INFO-LIST', 'infolist', 'fa fa-fw fa-circle-o', 'example/box/info-list.vue')
    ])
    , new MenuItem('表单', 'form', 'fa fa-fw fa-edit', '', [
        new MenuItem('表单', 'form', 'fa fa-fw fa-circle-o', 'example/form/test-form.vue')
        , new MenuItem('表格', 'table', 'fa fa-fw fa-circle-o', 'example/form/test-table.vue')
        , new MenuItem('SMART表单', 'smart', 'fa fa-fw fa-circle-o', 'example/form/test-smart-form.vue')
        , new MenuItem('MARKDOWN', 'md', 'fa fa-fw fa-circle-o', 'example/form/test-markdown.vue')
        , new MenuItem('富文本框', 'editor', 'fa fa-fw fa-circle-o', 'example/form/test-editor.vue')
    ])
];

/**
 * 开发工具
 *
 * 非常实用的开发工具
 *
 * @type {*[]}
 */
const $tools = [
    new MenuItem('静态工具', 'tools', 'fa fa-fw fa-list', '', [
        new MenuItem('ICON', 'icon', '', 'tools/icons/index.vue')
        , new MenuItem('CODE', 'code', '', 'tools/code/index.vue')
        , new MenuItem('BLOG', 'blog', '', 'tools/blog/index.vue')
        , new MenuItem('FROG', 'frog', '', 'tools/frog/index.vue')
    ])
];

/**
 * GIS 开发代码样例
 *
 * @type {MenuItem[]}
 */
const $gis = [
    new MenuItem('基础图形', 'base', 'fa fa-fw fa-map', '', [
        new MenuItem('点', 'point', '', 'gis/base/point.vue')
        , new MenuItem('线', 'line', '', 'gis/base/line.vue')
        , new MenuItem('面', 'polygon', '', 'gis/base/polygon.vue')
        , new MenuItem('圆', 'circle', '', 'gis/base/circle.vue')
        , new MenuItem('几何叠加', 'polygons', '', 'gis/base/polygons.vue')
    ])
    , new MenuItem('地图绘制', 'draw', 'fa fa-fw fa-dashboard', '', [
        new MenuItem('点', 'point', '', 'gis/draw/point.vue')
        , new MenuItem('线', 'line', '', 'gis/draw/line.vue')
        , new MenuItem('编辑 Modify', 'modify', '', 'gis/draw/modify.vue')
        , new MenuItem('悬浮 Select', 'select', '', 'gis/draw/select.vue')
        , new MenuItem('画布 Canvas', 'canvas', '', 'gis/draw/canvas.vue')
    ])
    , new MenuItem('常规业务', 'general', 'fa fa-fw fa-map-o', '', [
        new MenuItem('告警特效', 'warning', '', 'gis/general/warning.vue')
        , new MenuItem('吸附窗口', 'popover', '', 'gis/general/popover.vue')
        , new MenuItem('设备展示', 'show', '', 'gis/general/show.vue')
        , new MenuItem('设备排布', 'device', '', 'gis/general/device.vue')
        , new MenuItem('设备选点', 'select', '', 'gis/general/select.vue')
    ])
    , new MenuItem('地图接入', 'online', 'fa fa-fw fa-chain', '', [
        new MenuItem('天地图', 'tianditu', '', 'gis/online/tianditu.vue')
    ])
];

/**
 * 静态菜单
 *
 * 与 $core 同级的菜单，但是不显示在菜单栏上，
 *
 * 主要是一些与主营业务无关的辅助的功能
 *
 * @type {*[]}
 */
const $static = [
    new MenuItem('文档管理', 'doc', 'fa fa-fw fa-list', '', [
        new MenuItem('OpenAPI', 'open-api', '', 'core/doc/open-api/index.vue')
        , new MenuItem('接口文档', 'api-mapping', '', 'core/doc/api-mapping/index.vue')
        , new MenuItem('Mybatis', 'ibatis', '', 'core/doc/ibatis/index.vue')
        , new MenuItem('服务器信息', 'props', '', 'core/doc/props/index.vue')
    ])
    , new MenuItem('系统日志', 'log', 'fa fa-fw fa-list', '', [
        new MenuItem('登录日志', 'login', '', 'core/log/login.vue')
        , new MenuItem('访问日志', 'access', '', 'core/log/access.vue')
        , new MenuItem('运行日志', 'slf4j', '', 'core/log/slf4j.vue')
    ])
];

/**
 * 核心业务
 *
 * 包含一些系统初始化的业务
 *
 * @type {MenuItem[]}
 */
const $core = [
    new MenuItem('系统授权', 'auth', 'fa fa-fw fa-list', '', [
        new MenuItem('角色', 'role', '', 'core/auth/role/index.vue')
        , new MenuItem('部门', 'dept', '', 'core/auth/dept/index.vue')
        , new MenuItem('用户', 'user', '', 'core/auth/user/index.vue')
        , new MenuItem('星级', 'star', '', 'core/auth/star/index.vue')
    ])
    , new MenuItem('初始化', 'init', 'fa fa-fw fa-hourglass-3', '', [
        new MenuItem('菜单配置', 'menu', '', 'core/init/menu/index.vue')
        , new MenuItem('权限配置', 'permit', '', 'core/init/permit/index.vue')
        , new MenuItem('角色配置', 'role', '', 'core/init/role/index.vue')
        , new MenuItem('数据字典', 'dic', '', 'core/init/dic/index.vue')
        , new MenuItem('机构配置', 'organization', '', 'core/init/organization/index.vue')
    ])
    , new MenuItem('智能模块', 'turing', 'fa fa-fw fa-laptop', '', [
        new MenuItem('逆向工程', 'gen', 'fa fa-fw fa-circle-o', 'turing/gen/index.vue')
        , new MenuItem('客户海报', 'poster', 'fa fa-fw fa-circle-o', 'turing/poster/index.vue')
    ])
];

/**
 * 递归处理 MenuItem，将菜单信息转为真实路由
 *
 * @param menus {[MenuItem]} - 菜单列表
 * @param parent {string} - 父级路由
 * @param uri {string} - 基础路径，用于拼接 route- path 的
 */
const parseMenu = (menus, parent, uri = '') => {
    for (let i = 0; i < menus.length; i++) {
        const menu = menus[i];

        // path 不必与 url 保持一致，可以定制自己的规则
        menu.path = uri + '/' + menu.name;

        // 页面名称，可以理解成唯一 ID，与 path 功能基本一致，也可以用于路由
        menu.route_name = menu.path.replaceAll('/', '_');
        if (Layers.isNotEmpty(menu.src)) {

            // url 拼接方式，由 vite glob 功能决定
            let url = '../view/' + menu.src;

            // 添加到路由
            const raw = {
                name: menu.route_name,
                label: menu.title,
                path: menu.path,
                component: modules[url]
            };

            if (parent) {
                router.addRoute(parent, raw);
            } else {
                router.addRoute(raw);
            }
        } else {
            if (menu.children !== undefined) {
                // 递归处理自己
                parseMenu(menu.children, parent, menu.path);
            }
        }
    }
}

/**
 * 查询主菜单
 */
const getManus = (): Promise<MenuItem[]> => {
    return Promise.resolve($core);
}


/**
 * 查询代码样例
 */
const getExamples = (): Promise<MenuItem[]> => {
    return Promise.resolve($example);
}


/**
 * 查询代码样例
 */
const getGis = (): Promise<MenuItem[]> => {
    return Promise.resolve($gis);
}


/**
 * 将路由添加到
 *
 * 注意此函数不允许异步执行，否则浏览器在刷新的时候，无法直接进入指定界面。
 *
 * @param r 路由对象
 */
const pushMenus = (r) => {
    router = r;

    // 二级路由：GIS
    parseMenu($gis, 'gis', '/gis');

    // 以及路由：工具栏
    parseMenu($tools, null, '');

    // 二级路由：基础样例组件
    parseMenu($example, 'sample', '/sample');

    // 二级路由：工具界面
    parseMenu($static, 'core', '/core');

    // 二级路由：核心业务
    parseMenu($core, 'core', '/core');
}

export default {pushMenus, getManus, getExamples, getGis}